'use strict';

/**  */
const URL_DEVICES = "https://gitee.com/loupman/alexa-camara-skill/raw/master/mock/devices.json";
const URL_RETRIEVE_URI = "https://gitee.com/loupman/alexa-camara-skill/raw/master/mock/camera-uri.json";

import https from 'node:https';

// const https = require('https');
function log(title, msg) {
    console.log(`\n[${title}] ${msg}\n`);
}

/**
 *  Usage:
 *  randomString(8, 16), generate 8 length hex str
 *  randomString(8), generate 8 length alpha and number str
 */
function randomString(len, bits)
{
    bits = bits || 36;
    var outStr = "", newStr;
    while (outStr.length < len)
    {
        newStr = Math.random().toString(bits).slice(2);
        outStr += newStr.slice(0, Math.min(newStr.length, (len - outStr.length)));
    }
    return outStr.toUpperCase();
}

function generateMessageID() {
    return '38A28869-DD5E-48CE-BBE5-' + randomString(12, 16); // Dummy
}

function responseDiscovery(callback, discoveredDevices){
    const response = {
        event:{
            header: {
                messageId: generateMessageID(),
                name: 'Discover.Response',
                namespace: 'Alexa.Discovery',
                payloadVersion: '3',
            },
            payload: {
                endpoints: discoveredDevices,
            },
        }
    };
    log('DEBUG', `Discovery Response: ${JSON.stringify(response)}`);
    callback(null, response);
}

function handleDiscovery(request, callback) {
    const userAccessToken = request.directive.payload.scope.token.trim();
    let url = URL_DEVICES + '?access_token=' + userAccessToken;
    
    log('DEBUG', `\nDiscovery Request URL: ${url}\nRequest: ${JSON.stringify(request)}\n`);
    
    let resStr = '[ { "endpointId": "IPC-T-12R21SSS9QH3", "manufacturerName": "Jovision", "modelName": "ModelNameDesc", "friendlyName": "Jovision Camera", "description": "This is Jovision Camera", "displayCategories": [ "CAMERA" ], "cookie": { "key1": "arbitrary key/value pairs for skill to reference this endpoint.", "key2": "There can be multiple entries", "key3": "but they should only be used for reference purposes.", "key4": "This is not a suitable place to maintain current endpoint state." }, "capabilities": [ { "type": "AlexaInterface", "interface": "Alexa.CameraStreamController", "version": "3", "cameraStreamConfigurations": [ { "protocols": [ "RTSP" ], "resolutions": [ { "width": 1920, "height": 1080 }, { "width": 1280, "height": 720 } ], "authorizationTypes": [ "BASIC" ], "videoCodecs": [ "H264", "MPEG2" ], "audioCodecs": [ "G711A" ] }, { "protocols": [ "RTSP" ], "resolutions": [ { "width": 1920, "height": 1080 }, { "width": 1280, "height": 720 } ], "authorizationTypes": [ "NONE" ], "videoCodecs": [ "H264" ], "audioCodecs": [ "G711A" ] } ] }, { "type": "AlexaInterface", "interface": "Alexa.PowerController", "version": "3" } ] } ]';
    try {
        let result = JSON.parse(resStr);
        responseDiscovery(callback, result);
    } catch (error) {
        console.error("Error parsing JSON: " + error.message);
        responseDiscovery(callback, []);
    }
    
    // https.get(url, (res) => {
    //     log('状态码：', res.statusCode);
    //     log('请求头：', res.headers);
  
    //     res.on('data', (str) => {
    //         log("Get device list result: " + str);
    //         try {
    //             let result = JSON.parse(str);
    //             responseDiscovery(callback, result);
    //         } catch (error) {
    //             console.error("Error parsing JSON: " + error.message);
    //             responseDiscovery(callback, []);
    //         }
    //     });
    // }).on('error', (e) => {
    //     console.error(e);
    //     responseDiscovery(callback, []);
    // });
}

function responseRetrieveCameraUri(request, callback, name, playload){
    const userAccessToken = request.directive.endpoint.scope.token.trim();
    let deviceId = request.directive.endpoint.endpointId;
    const response = {
        event:{
            header: {
                namespace: 'Alexa.CameraStreamController',
                name: name,
                payloadVersion: '3',
                messageId: generateMessageID(),
                correlationToken: request.directive.header.correlationToken,
            },
            payload: playload,
            endpoint: {
                scope: {
                    type: "BearerToken",
                    token: userAccessToken
                },
                endpointId: deviceId,
            },
            
        }
    };
    log('DEBUG', `Query Response: ${JSON.stringify(response)}`);
    callback(null, response);
}

function handleRetrieveCameraUri(request, callback){
    const userAccessToken = request.directive.endpoint.scope.token.trim();

    let deviceId = request.directive.endpoint.endpointId;
    let url = URL_RETRIEVE_URI + '?access_token=' + userAccessToken + "&deviceId=" + deviceId;
    
    log('DEBUG', `\nDiscovery Request URL: ${url}\nRequest: ${JSON.stringify(request)}`);
    
    let resStr = '{ "uri": "rtsp://admin:admin123@172.20.10.147:8554/live0", "proxy": "rtsp://bbe13e34-7c28-467c-a255-1f75787327a1.mproxy.io:443/STREAM:87b75d51-7269-4a0c-b58c-eff83e1335e9?session=757f0283-34bc-442a-81e9-1f89c2b95272", "resolution": { "width": "192", "height": "192" }, "authorizationType": "BASIC", "videoCodec": "H264", "audioCodec": "G711", "protocol": "RTSP" } ';
    try {
        let result = JSON.parse(resStr);
        responseRetrieveCameraUri(request, callback, 'Response', {
            cameraStreams:[ result ],
        });
    } catch (error) {
        console.error("Error parsing JSON: " + error.message);
        responseRetrieveCameraUri(request, callback, 'Response', error);
    }
    
    // https.get(url, (res) => {
    //     var str = "";
    //     res.on('data', (d) => {
    //         str += d;
    //     });
    //     res.on('end', function () {
    //         log("Retrieve camera uri result: " + str);
    //         let result = JSON.parse(str);
    //         let rtspUri = result.uri;
    //         responseRetrieveCameraUri(request, callback, 'Response', {
    //             cameraStreams:[
    //                 {
    //                     uri: rtspUri,
    //                     idleTimeoutSeconds: 15,
    //                     protocol: "RTSP",
    //                     resolution: {
    //                         width: 640,
    //                         height: 480
    //                     },
    //                     authorizationType: "BASIC",
    //                     videoCodec: "H264",
    //                     audioCodec: "G711A"
    //                 }
    //             ],
    //         });
    //     });
    // }).on('error', (e) => {
    //     console.error(e);
    //     responseDiscovery(callback, []);
    // });
}

function handleQuery(request, callback){
    log('DEBUG', `Query Request: ${JSON.stringify(request)}`);
    switch (request.directive.header.name) {
        case 'InitializeCameraStreams': {
            handleRetrieveCameraUri(request, callback);
            break;
        }
        default:
            break;
    }
}

function handleAuthorization(request, callback){
    log('DEBUG', `Query Request: ${JSON.stringify(request)}`);
    switch (request.directive.header.name) {
        case 'AcceptGrant': {
            const response = {
                event:{
                    header: {
                        namespace: 'Alexa.Authorization',
                        name: 'AcceptGrant.Response',
                        payloadVersion: '3',
                        messageId: generateMessageID(),
                        correlationToken: request.directive.header.correlationToken,
                    },
                    payload: {},
                }
            };
            log('DEBUG', `Query Response: ${JSON.stringify(response)}`);
            callback(null, response);
        }
            break;
        default:
            break;
    }
}

export const handler = async(request, context, callback) => {
    switch (request.directive.header.namespace) {
        case 'Alexa.Discovery':
            handleDiscovery(request, callback);
            break;
        case 'Alexa.CameraStreamController':
            handleQuery(request, callback);
            break;
        case 'Alexa.Authorization': 
            handleAuthorization(request, callback);
                break;
        default: {
            const errorMessage = `No supported namespace: ${request.directive.header.namespace}`;
            log('ERROR', errorMessage);
            callback(new Error(errorMessage));
        }
    }
};